package com.trela.paymeontime.web.services;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import javax.annotation.Resource;

import org.joda.time.DateTime;
import org.springframework.stereotype.Component;

import com.trela.paymeontime.web.model.Payment;
import com.trela.paymeontime.web.model.PaymentItem;
import com.trela.paymeontime.web.model.UserSettings;
import com.trela.paymeontime.web.model.dao.DAO;
import com.trela.paymeontime.web.model.dto.PaymentContext;

@Component
public class PaymentsService {

    @Resource
    DAO dao;
    @Resource
    BalanceCalculator balanceCalculator;

    public PaymentContext createPaymentContext(UserSettings settings) {
        PaymentContext context = new PaymentContext();
        
        context.setPaymentItems(createPaymentItems(settings));
        context.setAssets(dao.getAssets());
        balanceCalculator.calculateAssets(context, settings);
        sortPayments(context.getPaymentItems());
        
        balanceCalculator.calculateBalance(context, settings);
        // TODO: balance date marker should be calculated somewhere else
        context.getBalanceInfo().setBalanceDateMarkerIndex(calculateBalanceDateTimeIndex(context));
        return context;
    }

    private void sortPayments(List<PaymentItem> paymentItems) {
        Collections.sort(paymentItems, new Comparator<PaymentItem>() {
            @Override
            public int compare(PaymentItem o1, PaymentItem o2) {
                return o1.getDueDate().compareTo(o2.getDueDate());
            }
        });
    }

    private List<PaymentItem> createPaymentItems(UserSettings settings) {
        List<PaymentItem> paymentItems = new ArrayList<PaymentItem>();
        Collection<Payment> payments = dao.getPayments();
        for (Payment payment : payments) {
            paymentItems.add(new PaymentItem(payment, false, payment.getDueDate()));            
            paymentItems.addAll(duplicateRecurrentPayments(payment, settings));
        }
        return paymentItems;
    }

   
    private Collection<? extends PaymentItem> duplicateRecurrentPayments(Payment payment, UserSettings userSettings) {
        ArrayList<PaymentItem> items = new ArrayList<>();
        if(payment.getOccurence().getPeriod() != null){
            DateTime dueDate = payment.getDueDate();
            while((dueDate = dueDate.plus(payment.getOccurence().getPeriod())).isBefore(userSettings.getDisplayPaymentsUtil())){
                items.add(new PaymentItem(payment, false, dueDate));
            }
        }
        return items;
    }

    private int calculateBalanceDateTimeIndex(PaymentContext context) {
        int index = 0;
        for (PaymentItem paymentItem : context.getPaymentItems()) {
            if (context.getBalanceInfo().getBalanceDateTime().isBefore(paymentItem.getDueDate())) {
                return index;
            }
            index++;
        }
        return index;
    }

}
